package com.css.crm.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.SortClause;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;

import com.css.crm.dao.CustomerActivityDao;
import com.css.crm.dao.CustomerAddressAuditTrailDao;
import com.css.crm.dao.CustomerAddressDao;
import com.css.crm.dao.CustomerAuditTrailDao;
import com.css.crm.dao.CustomerAttributeAuditTrailDao;
import com.css.crm.dao.CustomerAttributeDao;
import com.css.crm.dao.CustomerDao;
import com.css.crm.dao.CustomerDiscountAuditTrailDao;
import com.css.crm.dao.CustomerDiscountDao;
import com.css.crm.dao.CustomerEmailAuditTrailDao;
import com.css.crm.dao.CustomerEmailDao;
import com.css.crm.dao.CustomerServiceEventAuditTrailDao;
import com.css.crm.dao.CustomerServiceEventDao;
import com.css.crm.dao.CustomerTelephoneAuditTrailDao;
import com.css.crm.dao.CustomerTelephoneDao;
import com.css.crm.dao.impl.CustomerActivityDaoImpl;
import com.css.crm.dao.impl.CustomerAddressAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerAddressDaoImpl;
import com.css.crm.dao.impl.CustomerAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerAttributeAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerAttributeDaoImpl;
import com.css.crm.dao.impl.CustomerDaoImpl;
import com.css.crm.dao.impl.CustomerDiscountAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerDiscountDaoImpl;
import com.css.crm.dao.impl.CustomerEmailAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerEmailDaoImpl;
import com.css.crm.dao.impl.CustomerServiceEventAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerServiceEventDaoImpl;
import com.css.crm.dao.impl.CustomerTelephoneAuditTrailDaoImpl;
import com.css.crm.dao.impl.CustomerTelephoneDaoImpl;
import com.css.crm.exception.SystemException;
import com.css.crm.message.SystemErrorMessage;
import com.css.crm.service.CustomerService;
import com.css.crm.utility.AuditTrailUtil;
import com.css.crm.utility.ConstantUtil;
import com.css.crm.utility.DateUtil;
import com.css.crm.utility.ResourceUtil;
import com.css.crm.utility.SystemUtil;
import com.css.crm.utility.ValidateUtil;
import com.css.crm.vo.CustomerAddressVo;
import com.css.crm.vo.CustomerAttributeVo;
import com.css.crm.vo.CustomerDiscountVo;
import com.css.crm.vo.CustomerEmailVo;
import com.css.crm.vo.CustomerServiceEventVo;
import com.css.crm.vo.CustomerTelephoneVo;
import com.css.crm.vo.CustomerVo;

/**
 * Implementation of customer service
 * 
 * @author AIS
 */
public class CustomerServiceImpl extends BaseServiceImpl implements CustomerService {

	private CustomerDao customerDao = null;
	private CustomerAttributeDao customerAttributeDao = null;
	private CustomerAddressDao customerAddressDao = null;
	private CustomerTelephoneDao customerTelephoneDao = null;
	private CustomerEmailDao customerEmailDao = null;
	private CustomerDiscountDao customerDiscountDao = null;
	private CustomerServiceEventDao customerServiceEventDao = null;
	private CustomerActivityDao customerActivityDao = null;

	private CustomerAuditTrailDao customerAuditTrailDao = null;
	private CustomerAttributeAuditTrailDao customerAttributeAuditTrailDao = null;
	private CustomerAddressAuditTrailDao customerAddressAuditTrailDao = null;
	private CustomerTelephoneAuditTrailDao customerTelephoneAuditTrailDao = null;
	private CustomerEmailAuditTrailDao customerEmailAuditTrailDao = null;
	private CustomerDiscountAuditTrailDao customerDiscountAuditTrailDao = null;
	private CustomerServiceEventAuditTrailDao customerServiceEventAuditTrailDao = null;

	public CustomerServiceImpl() {
		customerDao = new CustomerDaoImpl();

		customerAttributeDao = new CustomerAttributeDaoImpl();
		customerAddressDao = new CustomerAddressDaoImpl();
		customerTelephoneDao = new CustomerTelephoneDaoImpl();
		customerEmailDao = new CustomerEmailDaoImpl();
		customerDiscountDao = new CustomerDiscountDaoImpl();
		customerServiceEventDao = new CustomerServiceEventDaoImpl();
		customerActivityDao = new CustomerActivityDaoImpl();

		customerAuditTrailDao = new CustomerAuditTrailDaoImpl();
		customerAttributeAuditTrailDao = new CustomerAttributeAuditTrailDaoImpl();
		customerAddressAuditTrailDao = new CustomerAddressAuditTrailDaoImpl();
		customerTelephoneAuditTrailDao = new CustomerTelephoneAuditTrailDaoImpl();
		customerEmailAuditTrailDao = new CustomerEmailAuditTrailDaoImpl();
		customerDiscountAuditTrailDao = new CustomerDiscountAuditTrailDaoImpl();
		customerServiceEventAuditTrailDao = new CustomerServiceEventAuditTrailDaoImpl();
	}

	@Override
	protected void initDaoSession() {
		// set same sqlsession for all dao
		customerDao.setMyBatisSession(getSession());
		customerAttributeDao.setMyBatisSession(getSession());
		customerAddressDao.setMyBatisSession(getSession());
		customerTelephoneDao.setMyBatisSession(getSession());
		customerEmailDao.setMyBatisSession(getSession());
		customerDiscountDao.setMyBatisSession(getSession());
		customerServiceEventDao.setMyBatisSession(getSession());
		customerActivityDao.setMyBatisSession(getSession());

		customerAuditTrailDao.setMyBatisSession(getSession());
		customerAttributeAuditTrailDao.setMyBatisSession(getSession());
		customerAddressAuditTrailDao.setMyBatisSession(getSession());
		customerTelephoneAuditTrailDao.setMyBatisSession(getSession());
		customerEmailAuditTrailDao.setMyBatisSession(getSession());
		customerDiscountAuditTrailDao.setMyBatisSession(getSession());
		customerServiceEventAuditTrailDao.setMyBatisSession(getSession());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#setCustomerList(com.css.crm.vo.CustomerVo
	 * )
	 */
	@Override
	public CustomerVo setCustomerList(CustomerVo customer) throws SystemException {
		String custId = customer.getCustId();

		try {
			List<CustomerAddressVo> customerAddressList = new ArrayList<>();
			customerAddressList = customerAddressDao.getCustomerAddressByCustId(custId);
			customer.setCustomerAddressList(customerAddressList);
			if (customerAddressList != null) {
				for (CustomerAddressVo addressVo : customerAddressList) {
					addressVo.initItems();
					addressVo.setOrigiVo(addressVo.clone());
				}
			}

			List<CustomerEmailVo> customerEmaiList = new ArrayList<>();
			customerEmaiList = customerEmailDao.getCustomerEmailByCustId(custId);
			customer.setCustomerEmailList(customerEmaiList);
			if (customerEmaiList != null) {
				for (CustomerEmailVo emailVo : customerEmaiList) {
					emailVo.setOrigiVo(emailVo.clone());

				}
			}

			List<CustomerTelephoneVo> customerTelephoneList = new ArrayList<>();
			customerTelephoneList = customerTelephoneDao.getCustomerTelephoneByCustId(custId);
			customer.setCustomerTelephoneList(customerTelephoneList);
			if (customerTelephoneList != null) {
				for (CustomerTelephoneVo telephoneVo : customerTelephoneList) {
					telephoneVo.setOrigiVo(telephoneVo.clone());
				}
			}

			List<CustomerAttributeVo> customerAttributeList = new ArrayList<>();
			customerAttributeList = customerAttributeDao.getCustomerAttributeByCustId(custId);
			customer.setCustomerAttributeList(customerAttributeList);
			if (customerAttributeList != null) {
				for (CustomerAttributeVo attributeVo : customerAttributeList) {
					attributeVo.setOrigiVo(attributeVo.clone());
				}
			}

			List<CustomerDiscountVo> customerDiscountList = new ArrayList<>();
			customerDiscountList = customerDiscountDao.getCustomerDiscountByCustId(custId);
			customer.setCustomerDiscountList(customerDiscountList);
			if (customerDiscountList != null) {
				for (CustomerDiscountVo discountVo : customerDiscountList) {
					discountVo.setOrigiVo(discountVo.clone());
				}
			}

			List<CustomerServiceEventVo> customerServiceEventList = new ArrayList<>();
			customerServiceEventList = customerServiceEventDao.getCustomerServiceEventByCustId(custId);
			customer.setCustomerServiceEventList(customerServiceEventList);
			if (customerServiceEventList != null) {
				for (CustomerServiceEventVo serviceEventVo : customerServiceEventList) {
					serviceEventVo.setOrigiVo(serviceEventVo.clone());
				}
			}
		} catch (Exception e) {
			throw new SystemException(SystemErrorMessage.SQL_UNEXPECTED_EXCEPTION, e);
		}
		return customer;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#getCustomerByCustId(java.lang.String)
	 */
	@Override
	public CustomerVo getCustomerByCustId(String custId) throws SystemException {
		try {
			customerDao.setMyBatisSession(getSession());
			return customerDao.getCustomerByPK(custId);
		} catch (Exception e) {
			throw new SystemException(SystemErrorMessage.SQL_UNEXPECTED_EXCEPTION, e);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#updateCustomer(com.css.crm.vo.CustomerVo
	 * )
	 */
	@Override
	public void updateCustomer(CustomerVo customer) throws SystemException {
		try {
			// delete record
			if (customer.getCustomerAttributeListDeleted() != null && customer.getCustomerAttributeListDeleted().size() > 0) {
				for (CustomerAttributeVo attributeVo : customer.getCustomerAttributeListDeleted()) {
					if (attributeVo.getCustAttrId() == null || attributeVo.getCustAttrId().intValue() == 0) {
						continue;
					}
					customerAttributeDao.deleteCustomerAttributeByPK(attributeVo.getCustAttrId());
					if (customer.getCustomerAttributeList() != null && !customer.getCustomerAttributeList().contains(attributeVo)) {
						// if new list not contain deleted record, then record
						// this operation
						customerAttributeAuditTrailDao.insertCustomerAttributeAuditTrail(AuditTrailUtil.getDeleteAuditTrail(attributeVo));
					}
				}
			}

			if (customer.getCustomerAddressListDeleted() != null && customer.getCustomerAddressListDeleted().size() > 0) {
				for (CustomerAddressVo addressVo : customer.getCustomerAddressListDeleted()) {
					if (addressVo.getCustAddrId() == null || addressVo.getCustAddrId().intValue() == 0) {
						continue;
					}
					customerAddressDao.deleteCustomerAddressByPK(addressVo.getCustAddrId());
					if (customer.getCustomerAddressList() != null && !customer.getCustomerAddressList().contains(addressVo)) {
						// if new list not contain deleted record, then record
						// this operation
						customerAddressAuditTrailDao.insertCustomerAddressAuditTrail(AuditTrailUtil.getDeleteAuditTrail(addressVo));
					}

				}
			}

			if (customer.getCustomerTelephoneListDeleted() != null && customer.getCustomerTelephoneListDeleted().size() > 0) {
				for (CustomerTelephoneVo telephoneVo : customer.getCustomerTelephoneListDeleted()) {
					if (telephoneVo.getCustTelId() == null || telephoneVo.getCustTelId().intValue() == 0) {
						continue;
					}
					customerTelephoneDao.deleteCustomerTelephoneByPK(telephoneVo.getCustTelId());
					if (customer.getCustomerTelephoneList() != null && !customer.getCustomerTelephoneList().contains(telephoneVo)) {
						// if new list not contain deleted record, then record
						// this operation
						customerTelephoneAuditTrailDao.insertCustomerTelephoneAuditTrail(AuditTrailUtil.getDeleteAuditTrail(telephoneVo));
					}

				}
			}

			if (customer.getCustomerEmailListDeleted() != null && customer.getCustomerEmailListDeleted().size() > 0) {
				for (CustomerEmailVo emailVo : customer.getCustomerEmailListDeleted()) {
					if (emailVo.getCustEmailId() == null || emailVo.getCustEmailId().intValue() == 0) {
						continue;
					}
					customerEmailDao.deleteCustomerEmailByPK(emailVo.getCustEmailId());
					if (customer.getCustomerEmailList() != null && !customer.getCustomerEmailList().contains(emailVo)) {
						// if new list not contain deleted record, then record
						// this operation
						customerEmailAuditTrailDao.insertCustomerEmailAuditTrail(AuditTrailUtil.getDeleteAuditTrail(emailVo));
					}

				}
			}

			if (customer.getCustomerDiscountListDeleted() != null && customer.getCustomerDiscountListDeleted().size() > 0) {
				for (CustomerDiscountVo discountVo : customer.getCustomerDiscountListDeleted()) {
					if (discountVo.getCustDiscId() == null || discountVo.getCustDiscId().intValue() == 0) {
						continue;
					}
					customerDiscountDao.deleteCustomerDiscountByPK(discountVo.getCustDiscId());
					if (customer.getCustomerDiscountList() != null && !customer.getCustomerDiscountList().contains(discountVo)) {
						// if new list not contain deleted record, then record
						// this operation
						customerDiscountAuditTrailDao.insertCustomerDiscountAuditTrail(AuditTrailUtil.getDeleteAuditTrail(discountVo));
					}

				}
			}

			if (customer.getCustomerServiceEventListDeleted() != null && customer.getCustomerServiceEventListDeleted().size() > 0) {
				for (CustomerServiceEventVo serviceEventVo : customer.getCustomerServiceEventListDeleted()) {
					if (serviceEventVo.getCustServEventId() == null || serviceEventVo.getCustServEventId().intValue() == 0) {
						continue;
					}
					customerServiceEventDao.deleteCustomerServiceEventByPK(serviceEventVo.getCustServEventId());
					if (customer.getCustomerServiceEventList() != null && !customer.getCustomerServiceEventList().contains(serviceEventVo)) {
						// if new list not contain deleted record, then record
						// this operation
						customerServiceEventAuditTrailDao.insertCustomerServiceEventAuditTrail(AuditTrailUtil.getDeleteAuditTrail(serviceEventVo));
					}

				}
			}

			// modify customer
			if (customer.compareTo(customer.getOrigiVo()) != 0) {
				// check if update some fields of customer
				customerDao.updateCustomerByPK(customer);
				customerAuditTrailDao.insertCustomerAuditTrail(AuditTrailUtil.getUpdateAuditTrail(customer));
			}

			String custId = customer.getCustId();
			// modify customer attributes, delete first then create
			if (customer.getCustomerAttributeList() != null && customer.getCustomerAttributeList().size() > 0) {
				for (CustomerAttributeVo attributeVo : customer.getCustomerAttributeList()) {
					if (StringUtils.isEmpty(attributeVo.getAttrCde()) || StringUtils.isEmpty(attributeVo.getAttrVal()))
						continue;

					if (attributeVo.getCustAttrId() == null) {
						attributeVo.setCustId(custId);
						customerAttributeDao.insertCustomerAttribute(attributeVo);
					} else if (!attributeVo.equals(attributeVo.getOrigiVo())) {
						customerAttributeDao.updateCustomerAttributeByPK(attributeVo);
						customerAttributeAuditTrailDao.insertCustomerAttributeAuditTrail(AuditTrailUtil.getUpdateAuditTrail(attributeVo));
					}

				}
			}
			// modify customer address
			if (customer.getCustomerAddressList() != null && customer.getCustomerAddressList().size() > 0) {
				for (CustomerAddressVo addressVo : customer.getCustomerAddressList()) {
					if (addressVo.getPlaceId() == null || addressVo.getPlaceId() == 0) {
						continue;
					}
					if (addressVo.getCustAddrId() == null) {
						addressVo.setCustId(custId);
						customerAddressDao.insertCustomerAddress(addressVo);
					} else if (!addressVo.equals(addressVo.getOrigiVo())) {
						customerAddressDao.updateCustomerAddressByPK(addressVo);
						customerAddressAuditTrailDao.insertCustomerAddressAuditTrail(AuditTrailUtil.getUpdateAuditTrail(addressVo));
					}

				}
			}
			// modify customer telephone
			if (customer.getCustomerTelephoneList() != null && customer.getCustomerTelephoneList().size() > 0) {
				for (CustomerTelephoneVo telephoneVo : customer.getCustomerTelephoneList()) {
					if (StringUtils.isEmpty(telephoneVo.getTypeCde()) || StringUtils.isEmpty(telephoneVo.getTelNbr()))
						continue;
					if (telephoneVo.getCustTelId() == null) {
						telephoneVo.setCustId(custId);
						customerTelephoneDao.insertCustomerTelephone(telephoneVo);
					} else if (!telephoneVo.equals(telephoneVo.getOrigiVo())) {
						customerTelephoneDao.updateCustomerTelephoneByPK(telephoneVo);
						customerTelephoneAuditTrailDao.insertCustomerTelephoneAuditTrail(AuditTrailUtil.getUpdateAuditTrail(telephoneVo));
					}

				}
			}
			// modify customer email
			if (customer.getCustomerEmailList() != null && customer.getCustomerEmailList().size() > 0) {
				for (CustomerEmailVo emailVo : customer.getCustomerEmailList()) {
					if (StringUtils.isEmpty(emailVo.getTypeCde()) || StringUtils.isEmpty(emailVo.getEmail()))
						continue;
					if (emailVo.getCustEmailId() == null) {
						emailVo.setCustId(custId);
						customerEmailDao.insertCustomerEmail(emailVo);
					} else if (!emailVo.equals(emailVo.getOrigiVo())) {
						customerEmailDao.updateCustomerEmailByPK(emailVo);
						customerEmailAuditTrailDao.insertCustomerEmailAuditTrail(AuditTrailUtil.getUpdateAuditTrail(emailVo));
					}

				}
			}
			// modify customer discount
			if (customer.getCustomerDiscountList() != null && customer.getCustomerDiscountList().size() > 0) {
				for (CustomerDiscountVo discountVo : customer.getCustomerDiscountList()) {
					if (StringUtils.isEmpty(discountVo.getDiscCde()))
						continue;
					if (discountVo.getCustDiscId() == null) {
						discountVo.setCustId(custId);
						customerDiscountDao.insertCustomerDiscount(discountVo);
					} else if (!discountVo.equals(discountVo.getOrigiVo())) {
						customerDiscountDao.updateCustomerDiscountByPK(discountVo);
						customerDiscountAuditTrailDao.insertCustomerDiscountAuditTrail(AuditTrailUtil.getUpdateAuditTrail(discountVo));
					}

				}
			}

			// modify customer services
			if (customer.getCustomerServiceEventList() != null && customer.getCustomerServiceEventList().size() > 0) {
				for (CustomerServiceEventVo serviceEventVo : customer.getCustomerServiceEventList()) {
					if (StringUtils.isEmpty(serviceEventVo.getEventCde()) || serviceEventVo.getEventDte() == null)
						continue;
					serviceEventVo.setCustId(custId);
					if (serviceEventVo.getCustServEventId() == null) {
						serviceEventVo.setCustId(customer.getCustId());
						customerServiceEventDao.insertCustomerServiceEvent(serviceEventVo);
					} else if (!serviceEventVo.equals(serviceEventVo.getOrigiVo())) {
						customerServiceEventDao.updateCustomerServiceEventByPK(serviceEventVo);
						customerServiceEventAuditTrailDao.insertCustomerServiceEventAuditTrail(AuditTrailUtil.getUpdateAuditTrail(serviceEventVo));
					}

				}
			}
		} catch (Exception e) {
			throw new SystemException(SystemErrorMessage.SQL_UNEXPECTED_EXCEPTION, e);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#updateCustomerCancelled(com.css.crm
	 * .vo.CustomerVo)
	 */
	@Override
	public void updateCustomerCancelled(CustomerVo customer) throws SystemException {
		try {

			String custId = customer.getCustId();
			// modify customer attributes
			if (customer.getCustomerAttributeList() != null && customer.getCustomerAttributeList().size() > 0) {
				for (CustomerAttributeVo attributeVo : customer.getCustomerAttributeList()) {
					if (StringUtils.isEmpty(attributeVo.getAttrCde()) || StringUtils.isEmpty(attributeVo.getAttrVal()))
						continue;

					if (attributeVo.getCustAttrId() == null) {
						attributeVo.setCustId(custId);
					}
					customerAttributeAuditTrailDao.insertCustomerAttributeAuditTrail(AuditTrailUtil.getDeleteAuditTrail(attributeVo));

				}
			}
			// modify customer address
			if (customer.getCustomerAddressList() != null && customer.getCustomerAddressList().size() > 0) {
				for (CustomerAddressVo addressVo : customer.getCustomerAddressList()) {
					if (addressVo.getPlaceId() == null || addressVo.getPlaceId() == 0) {
						continue;
					}
					if (addressVo.getCustAddrId() == null) {
						addressVo.setCustId(custId);
					}
					customerAddressAuditTrailDao.insertCustomerAddressAuditTrail(AuditTrailUtil.getDeleteAuditTrail(addressVo));

				}
			}
			// modify customer telephone
			if (customer.getCustomerTelephoneList() != null && customer.getCustomerTelephoneList().size() > 0) {
				for (CustomerTelephoneVo telephoneVo : customer.getCustomerTelephoneList()) {
					if (StringUtils.isEmpty(telephoneVo.getTypeCde()) || StringUtils.isEmpty(telephoneVo.getTelNbr()))
						continue;
					if (telephoneVo.getCustTelId() == null) {
						telephoneVo.setCustId(custId);
					}
					customerTelephoneAuditTrailDao.insertCustomerTelephoneAuditTrail(AuditTrailUtil.getDeleteAuditTrail(telephoneVo));

				}
			}
			// modify customer email
			if (customer.getCustomerEmailList() != null && customer.getCustomerEmailList().size() > 0) {
				for (CustomerEmailVo emailVo : customer.getCustomerEmailList()) {
					if (StringUtils.isEmpty(emailVo.getTypeCde()) || StringUtils.isEmpty(emailVo.getEmail()))
						continue;
					if (emailVo.getCustEmailId() == null) {
						emailVo.setCustId(custId);
					}
					customerEmailAuditTrailDao.insertCustomerEmailAuditTrail(AuditTrailUtil.getDeleteAuditTrail(emailVo));

				}
			}
			// modify customer discount
			if (customer.getCustomerDiscountList() != null && customer.getCustomerDiscountList().size() > 0) {
				for (CustomerDiscountVo discountVo : customer.getCustomerDiscountList()) {
					if (StringUtils.isEmpty(discountVo.getDiscCde()))
						continue;
					if (discountVo.getCustDiscId() == null) {
						discountVo.setCustId(custId);
					}
					customerDiscountAuditTrailDao.insertCustomerDiscountAuditTrail(AuditTrailUtil.getDeleteAuditTrail(discountVo));

				}
			}

			// modify customer services
			if (customer.getCustomerServiceEventList() != null && customer.getCustomerServiceEventList().size() > 0) {
				for (CustomerServiceEventVo serviceEventVo : customer.getCustomerServiceEventList()) {
					if (StringUtils.isEmpty(serviceEventVo.getEventCde()) || serviceEventVo.getEventDte() == null)
						continue;
					serviceEventVo.setCustId(custId);
					if (serviceEventVo.getCustServEventId() == null) {
						serviceEventVo.setCustId(customer.getCustId());
					}
					customerServiceEventAuditTrailDao.insertCustomerServiceEventAuditTrail(AuditTrailUtil.getDeleteAuditTrail(serviceEventVo));

				}
			}
		} catch (Exception e) {
			throw new SystemException(SystemErrorMessage.SQL_UNEXPECTED_EXCEPTION, e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#createCustomer(com.css.crm.vo.CustomerVo
	 * )
	 */
	@Override
	public int createCustomer(CustomerVo customer) throws SystemException {
		int customerId = 0;
		try {
			// create customer
			customerId = customerDao.insertCustomer(customer);
			// create customer attributes
			if (customer.getCustomerAttributeList() != null && customer.getCustomerAttributeList().size() > 0) {
				for (CustomerAttributeVo attributeVo : customer.getCustomerAttributeList()) {
					if (StringUtils.isEmpty(attributeVo.getAttrCde()) || StringUtils.isEmpty(attributeVo.getAttrVal()))
						continue;
					attributeVo.setCustId(customer.getCustId());
					customerAttributeDao.insertCustomerAttribute(attributeVo);
				}
			}
			// create customer address
			if (customer.getCustomerAddressList() != null && customer.getCustomerAddressList().size() > 0) {
				for (CustomerAddressVo addressVo : customer.getCustomerAddressList()) {
					if (StringUtils.isEmpty(addressVo.getTypeCde()) || addressVo.getPlaceId() == null || addressVo.getPlaceId() == 0)
						continue;
					addressVo.setCustId(customer.getCustId());
					customerAddressDao.insertCustomerAddress(addressVo);
				}
			}
			// create customer telephone
			if (customer.getCustomerTelephoneList() != null && customer.getCustomerTelephoneList().size() > 0) {
				for (CustomerTelephoneVo telephoneVo : customer.getCustomerTelephoneList()) {
					if (StringUtils.isEmpty(telephoneVo.getTypeCde()) || StringUtils.isEmpty(telephoneVo.getTelNbr()))
						continue;
					telephoneVo.setCustId(customer.getCustId());
					customerTelephoneDao.insertCustomerTelephone(telephoneVo);
				}
			}
			// create customer email
			if (customer.getCustomerEmailList() != null && customer.getCustomerEmailList().size() > 0) {
				for (CustomerEmailVo emailVo : customer.getCustomerEmailList()) {
					if (StringUtils.isEmpty(emailVo.getTypeCde()) || StringUtils.isEmpty(emailVo.getEmail()))
						continue;
					emailVo.setCustId(customer.getCustId());
					customerEmailDao.insertCustomerEmail(emailVo);
				}
			}
			// create customer discount
			if (customer.getCustomerDiscountList() != null && customer.getCustomerDiscountList().size() > 0) {
				for (CustomerDiscountVo discountVo : customer.getCustomerDiscountList()) {
					if (StringUtils.isEmpty(discountVo.getDiscCde()))
						continue;
					discountVo.setCustId(customer.getCustId());
					customerDiscountDao.insertCustomerDiscount(discountVo);
				}
			}
			// create customer service event
			if (customer.getCustomerServiceEventList() != null && customer.getCustomerServiceEventList().size() > 0) {
				for (CustomerServiceEventVo serviceEventVo : customer.getCustomerServiceEventList()) {
					if (StringUtils.isEmpty(serviceEventVo.getEventCde()) || serviceEventVo.getEventDte() == null)
						continue;
					serviceEventVo.setCustId(customer.getCustId());
					customerServiceEventDao.insertCustomerServiceEvent(serviceEventVo);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new SystemException(SystemErrorMessage.SQL_UNEXPECTED_EXCEPTION, e);
		}

		return customerId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#getDefaultDiscount(java.lang.String)
	 */
	@Override
	public CustomerDiscountVo getDefaultDiscount(String customerId) {
		return customerDiscountDao.getDefaultCustomerDiscount(customerId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#getContactEmail(java.lang.String)
	 */
	@Override
	public CustomerEmailVo getContactEmail(String customerId) {
		List<CustomerEmailVo> emailVos = customerEmailDao.getCustomerEmailByCustId(customerId);
		if (emailVos != null && emailVos.size() > 0) {
			for (CustomerEmailVo emailVo : emailVos) {
				if (ConstantUtil.COMMUNICATE_TYPE_CONTACT.equals(emailVo.getTypeCde())) {
					return emailVo;
				}
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#getContactAddress(java.lang.String)
	 */
	@Override
	public CustomerAddressVo getContactAddress(String customerId) {
		List<CustomerAddressVo> addressVos = customerAddressDao.getCustomerAddressByCustId(customerId);
		if (addressVos != null && addressVos.size() > 0) {
			for (CustomerAddressVo addressVo : addressVos) {
				if (ConstantUtil.COMMUNICATE_TYPE_CONTACT.equals(addressVo.getTypeCde())) {
					return addressVo;
				}
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#getContactTelephone(java.lang.String)
	 */
	@Override
	public CustomerTelephoneVo getContactTelephone(String customerId) {
		List<CustomerTelephoneVo> telephoneVos = customerTelephoneDao.getCustomerTelephoneByCustId(customerId);
		if (telephoneVos != null && telephoneVos.size() > 0) {
			for (CustomerTelephoneVo telephoneVo : telephoneVos) {
				if (ConstantUtil.COMMUNICATE_TYPE_CONTACT.equals(telephoneVo.getTypeCde())) {
					return telephoneVo;
				}
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.css.crm.service.CustomerService#searchCustomerBySolr(java.lang.String
	 * )
	 */
	@Override
	public List<CustomerVo> searchCustomerBySolr(String keyWord) throws SystemException {
		Properties solrConfig = ResourceUtil.getSolrConfig();
		String solrUrl = solrConfig.get(ConstantUtil.SOLR_SERVER_URL).toString();

		SolrServer server = new HttpSolrServer(solrUrl);
		SolrQuery query = new SolrQuery();
		query.setQuery("select");
		query.set("q", keyWord);
		query.set("defType", "edismax");
		query.set("qf", "custId namEng namZht namZhs email telNbr birthDay");// Query
																				// Fields
																				// for
																				// example
																				// fieldOne^2.3
																				// fieldTwo
																				// fieldThree^0.4
		query.set("mm", "1");// Minimum 'Should' Match the query At least number
		query.set("qs", "3");// Query Phrase Slop in qf fields
		//
		// query.set("pf", "namEng");//Phrase Fields
		// query.set("ps", "1");//Phrase Slop
		//
		// query.set("pf2", "namEng");//Phrase bigram Fields
		// query.set("ps2", "1");//Phrase bigram Slop
		//
		// query.set("pf3", "namEng");//Phrase trigram Fields
		// query.set("ps3", "1");//Phrase trigram Slop
		//
		// query.set("bq", "1");//Boost Query

		query.set("shards.tolerant", "true");// if has shards down Still can use

		query.set("q.op", "AND");
		query.set("wt", "xml");
		String distrib = solrConfig.get(ConstantUtil.SOLR_QUERY_DISTRIB).toString();
		boolean distribInd = ConstantUtil.COMMON_YES.equals(distrib) ? true : false;
		query.setParam("distrib", distribInd);

		String rows = solrConfig.get(ConstantUtil.SOLR_QUERY_RECORD_LIMIT).toString();
		query.set("rows", rows);
		List<SortClause> listSort = new ArrayList<SortClause>();
		SortClause sc1 = new SortClause("custId", SolrQuery.ORDER.asc);
		listSort.add(sc1);
		query.setSorts(listSort);
		// query.setSort("name", SolrQuery.ORDER.asc);

		List<CustomerVo> customerList = null;

		try {
			QueryResponse rsp = server.query(query);
			customerList = rsp.getBeans(CustomerVo.class);
		} catch (SolrServerException e) {
			e.printStackTrace();
			throw new SystemException(SystemErrorMessage.SEARCH_CUSTOMER_FAILURE, e);
		}

		return customerList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.css.crm.service.CustomerService#getNextCustId(java.lang.Long)
	 */
	@Override
	public String getNextCustId(Long oriCtryCde) {
		return customerDao.getCustomerNextId(oriCtryCde);
	}

	private boolean invalidDayMonth(int month, int day) {
		switch (month) {
		case 2:
			return day > 29;
		case 4:
			return day > 30;
		case 6:
			return day > 30;
		case 9:
			return day > 30;
		case 11:
			return day > 30;
		default:
			return false;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.css.crm.service.CustomerService#validateCustomer(com.css.crm.vo.
	 * CustomerVo)
	 */
	@Override
	public boolean validateCustomer(CustomerVo customer) {
		boolean successFlag = true;

		// customer basic information validation
		if (!validateBaiscInfo(customer)) {
			successFlag = false;
		}

		// customer telephone validation
		if (!validateTelephone(customer)) {
			successFlag = false;
		}

		// customer email validation
		if (!validateEmail(customer)) {
			successFlag = false;
		}

		// customer address validation
		if (!validateAddress(customer)) {
			successFlag = false;
		}

		// customer attribute validate
		if (!validateAttribute(customer)) {
			successFlag = false;
		}

		// customer discount validate
		if (!validateDiscount(customer)) {
			successFlag = false;
		}

		// customer service event validate
		if (!validateServiceEvent(customer)) {
			successFlag = false;
		}

		return successFlag;
	}

	private boolean validateBaiscInfo(CustomerVo customer) {
		boolean successFlag = true;
		String lable = "";
		// customer basic info validation
		if (StringUtils.isEmpty(customer.getFrChanl())) {
			lable = ResourceUtil.getLabelString("label_membership_enrollment_channel");
			SystemUtil.addMessageError(SystemErrorMessage.INPUT_FIELD_REQUIRED.getSystemMessage(new String[] { lable }));
			successFlag = false;
		}
		if (StringUtils.isEmpty(customer.getNamEng()) && StringUtils.isEmpty(customer.getNamZhs()) && StringUtils.isEmpty(customer.getNamZht())) {
			lable = ResourceUtil.getLabelString("label_search_customer_name_en");
			String labelZhs = ResourceUtil.getLabelString("label_customer_name_simp");
			String labelZht = ResourceUtil.getLabelString("label_customer_name_chi");
			SystemUtil.addMessageError(SystemErrorMessage.CUSTOMER_NAME_REQUIRED.getSystemMessage(new String[] { lable, labelZhs, labelZht }));
			successFlag = false;
		}
		// validate customer dob info invalid Day/Month
		lable = ResourceUtil.getLabelString("label_search_customer_birthday");
		if (ValidateUtil.validateLeastOneNotEmpty(customer.getDobMonth(), customer.getDobDay())) {
			if (StringUtils.isEmpty(customer.getDobMonth()) || StringUtils.isEmpty(customer.getDobDay())) {
				SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
				successFlag = false;
			} else {
				int month = Integer.valueOf(customer.getDobMonth());
				int day = Integer.valueOf(customer.getDobDay());
				boolean flag = invalidDayMonth(month, day);
				if (flag) {
					SystemUtil.addMessageError(SystemErrorMessage.INPUT_DATE_VALID.getSystemMessage(new String[] { lable }));
					successFlag = false;
				}
			}
		}
		return successFlag;
	}

	private boolean validateTelephone(CustomerVo customer) {
		String lable = ResourceUtil.getLabelString("label_customer_phone");
		boolean successFlag = true;
		int contactCnt = 0;
		int validateCnt = 0;
		if (customer.getCustomerTelephoneList() != null && customer.getCustomerTelephoneList().size() > 0) {
			for (CustomerTelephoneVo telephoneVo : customer.getCustomerTelephoneList()) {
				// if all fields not be entered, then ignore this record
				if (ValidateUtil.isAllEmpty(telephoneVo.getCtryCde(), telephoneVo.getAreaCde(), telephoneVo.getTelNbr(), telephoneVo.getTypeCde())) {
					continue;
				}

				// if some fields not be entered, show error message
				if (!ValidateUtil.checkRecordIntact(telephoneVo.getCtryCde(), telephoneVo.getAreaCde(), telephoneVo.getTelNbr(), telephoneVo.getTypeCde())) {
					SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
					successFlag = false;
				}

				if (StringUtils.isNotEmpty(telephoneVo.getTelNbr()) && !ValidateUtil.validateNumber(telephoneVo.getTelNbr())) {
					SystemUtil.addMessageError(SystemErrorMessage.INPUT_FORMAT_VALID.getSystemMessage(new String[] { lable }));
					successFlag = false;
				}

				if (ConstantUtil.COMMUNICATE_TYPE_CONTACT.equals(telephoneVo.getTypeCde())) {
					contactCnt++;
				}

				validateCnt++;
			}

			// check single contact telephone registered for each customer
			if (contactCnt > 1) {
				SystemUtil.addMessageError(SystemErrorMessage.CONTACT_TELEPHONE_DUPLICATE.getSystemMessage());
				successFlag = false;
			}

			if (validateCnt > 0 && contactCnt < 1) {
				SystemUtil.addMessageError(SystemErrorMessage.CONTACT_TELEPHONE_REQUIRED.getSystemMessage());
				successFlag = false;
			}
		}

		return successFlag;
	}

	private boolean validateEmail(CustomerVo customer) {
		boolean successFlag = true;
		String lable = ResourceUtil.getLabelString("label_customer_email");
		int contactCnt = 0;
		int validateCnt = 0;
		if (customer.getCustomerEmailList() != null && customer.getCustomerEmailList().size() > 0) {
			for (CustomerEmailVo emailVo : customer.getCustomerEmailList()) {
				if (ValidateUtil.isAllEmpty(emailVo.getEmail(), emailVo.getTypeCde())) {
					continue;
				}

				if (StringUtils.isEmpty(emailVo.getEmail()) || StringUtils.isEmpty(emailVo.getTypeCde())) {
					SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
					successFlag = false;
				}

				if (!ValidateUtil.validateEmail(emailVo.getEmail())) {
					SystemUtil.addMessageError(SystemErrorMessage.INPUT_FORMAT_VALID.getSystemMessage());
					successFlag = false;
				}

				// check single contact email registered for each customer
				if (ConstantUtil.COMMUNICATE_TYPE_CONTACT.equals(emailVo.getTypeCde())) {
					contactCnt++;
				}

				validateCnt++;
			}
			if (contactCnt > 1) {
				SystemUtil.addMessageError(SystemErrorMessage.CONTACT_EMAIL_DUPLICATE.getSystemMessage());
				successFlag = false;
			}
			if (validateCnt > 0 && contactCnt < 1) {
				SystemUtil.addMessageError(SystemErrorMessage.CONTACT_EMAIL_REQUIRED.getSystemMessage());
				successFlag = false;
			}
		}

		return successFlag;
	}

	private boolean validateAddress(CustomerVo customer) {
		boolean successFlag = true;
		String lable = ResourceUtil.getLabelString("label_customer_address");
		int contactCnt = 0;
		int validateCnt = 0;
		if (customer.getCustomerAddressList() != null && customer.getCustomerAddressList().size() > 0) {
			for (CustomerAddressVo addressVo : customer.getCustomerAddressList()) {
				if (addressVo.getPlaceId() != null && addressVo.getPlaceId() == 0) {
					addressVo.setPlaceId(null);
				}
				if (addressVo.getCountryId() != null && addressVo.getCountryId() == 0) {
					addressVo.setCountryId(null);
				}
				if (addressVo.getProvinceId() != null && addressVo.getProvinceId() == 0) {
					addressVo.setProvinceId(null);
				}

				if (ValidateUtil.isAllEmpty(addressVo.getCountryId(), addressVo.getProvinceId(), addressVo.getPlaceId(), addressVo.getTypeCde(), addressVo.getAddr1(), addressVo.getAddr2(),
						addressVo.getAddr3(), addressVo.getDstrt(), addressVo.getZip())) {
					continue;
				}

				if (addressVo.getPlaceId() == null || StringUtils.isEmpty(addressVo.getTypeCde())) {
					SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
					successFlag = false;
					break;
				}

				if (ConstantUtil.COMMUNICATE_TYPE_CONTACT.equals(addressVo.getTypeCde())) {
					contactCnt++;
				}
				validateCnt++;
			}
			if (contactCnt > 1) {
				SystemUtil.addMessageError(SystemErrorMessage.CONTACT_ADDRESS_DUPLICATE.getSystemMessage());
				successFlag = false;
			}
			if (validateCnt > 0 && contactCnt < 1) {
				SystemUtil.addMessageError(SystemErrorMessage.CONTACT_ADDRESS_REQUIRED.getSystemMessage());
				successFlag = false;
			}
		}

		return successFlag;
	}

	private boolean validateAttribute(CustomerVo customer) {
		Map<String, String> dupMap = new HashMap<>();
		String lable = ResourceUtil.getLabelString("label_tab_attr_info");
		boolean successFlag = true;
		if (customer.getCustomerAttributeList() != null && customer.getCustomerAttributeList().size() > 0) {
			for (CustomerAttributeVo attributeVo : customer.getCustomerAttributeList()) {
				if (ValidateUtil.isAllEmpty(attributeVo.getAttrCde(), attributeVo.getAttrVal(), attributeVo.getRemark1(), attributeVo.getRemark2())) {
					continue;
				}

				if (StringUtils.isEmpty(attributeVo.getAttrCde()) || StringUtils.isEmpty(attributeVo.getAttrVal())) {
					SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
					successFlag = false;
					break;
				}

				if (dupMap.get(attributeVo.getAttrCde()) == null) {
					dupMap.put(attributeVo.getAttrCde(), attributeVo.getAttrCde());
				} else {
					SystemUtil.addMessageError(SystemErrorMessage.ATTRIBUTE_DUPLICATE.getSystemMessage());
					successFlag = false;
					break;
				}
			}
		}

		return successFlag;
	}

	private boolean validateDiscount(CustomerVo customer) {
		Map<String, String> dupMap = new HashMap<>();
		int defaultCnt = 0;
		String lable = ResourceUtil.getLabelString("label_tab_discount");
		boolean successFlag = true;
		if (customer.getCustomerDiscountList() != null && customer.getCustomerDiscountList().size() > 0) {
			for (CustomerDiscountVo discountVo : customer.getCustomerDiscountList()) {
				if (ValidateUtil.isAllEmpty(discountVo.getDiscCde(), discountVo.getExpiryDte(), discountVo.getDefltInd())) {
					continue;
				}

				if (ConstantUtil.COMMON_YES.equals(discountVo.getDefltInd())) {
					defaultCnt++;
				}

				if (StringUtils.isEmpty(discountVo.getDiscCde()) || StringUtils.isEmpty(discountVo.getDefltInd())) {
					SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
					successFlag = false;
					break;
				}
				String expDate = DateUtil.formatDate(discountVo.getExpiryDte());
				expDate = expDate == null ? "" : expDate;
				String key = discountVo.getDiscCde();
				if (dupMap.get(key) == null) {
					dupMap.put(key, discountVo.getDiscCde());
				} else {
					SystemUtil.addMessageError(SystemErrorMessage.DISCOUNT_DUPLICATE.getSystemMessage());
					successFlag = false;
					break;
				}

			}

			if (defaultCnt > 1) {
				SystemUtil.addMessageError(SystemErrorMessage.DISCOUNT_DEFAULT_DUPLICATE.getSystemMessage());
				successFlag = false;
			}
		}

		return successFlag;
	}

	private boolean validateServiceEvent(CustomerVo customer) {
		String lable = ResourceUtil.getLabelString("label_tab_customer_service");
		boolean successFlag = true;
		if (customer.getCustomerServiceEventList() != null && customer.getCustomerServiceEventList().size() > 0) {
			for (CustomerServiceEventVo serviceEventVo : customer.getCustomerServiceEventList()) {
				if (ValidateUtil.isAllEmpty(serviceEventVo.getEventCde(), serviceEventVo.getEventDesc(), serviceEventVo.getEventDte(), serviceEventVo.getRemark1(), serviceEventVo.getRemark2())) {
					continue;
				}
				if (StringUtils.isEmpty(serviceEventVo.getEventCde())) {
					SystemUtil.addMessageError(SystemErrorMessage.INFO_NOT_FULL.getSystemMessage(new String[] { lable }));
					successFlag = false;
					break;
				}
			}
		}

		return successFlag;
	}

}
